/*
 * LogPool.java	2009/03/10
 *
 * Copyright 2009 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Properties;

/**
 * This class holds all the created Log with a specific name. It also manage the lifecycle of a log and creation of new Log.
 * @author Leonardo Celati
 */
class LogPool<E extends Log> {
	
	/** Storage for our log */
	private ArrayList<Log> pool;
	/** Constructor for our log */
	private Constructor<?> cst;
	/** Property holder */
	private Properties p;
	
	/** Default constructor */
	public LogPool(Properties p) {
		this.init(p);
	}
	
	boolean add(E e) {
		return pool.add(e);
	}
	
	/**
	 * Initialize this pool
	 * @param p valid set of properties
	 */
	private void init(Properties p) {
		
		// we need this...
		this.p=p;
		
		// create a pool...
		pool = new ArrayList<Log>();

		// initialize our constructor for log...
        try {
        	// search for classname in property file...
            String classname = p.getProperty(Constant.PROP_ROOT + "log.classname", Constant.DEFAULT_LOG);
            // then...all that follows to get a valid constructor with reflection...
            Class<?> c = Class.forName(classname.trim());
            cst = c.getConstructor();
            

        } catch (RuntimeException e) {
            throw new LogPoolInitializationException(e);
        } catch (Exception e) {
            throw new LogPoolInitializationException(e);
        }
	}

	/**
	 * Find a log by its name
	 * @param name the name to look for
	 * @return a valid log if found
	 */
	private Log findByName(String name) {
		// browsing the pool...
		// we return a log if found and it's running
		for (Log l: pool) {
			if (l.getName().equals(name) && l.getStatus().equals(Log.Status.RUNNING) )
					return l;
		}
		// if we get here...we didn't found...
		return null;
	}

	/**
	 * Create a log
	 * @return a valid Log
	 */
	protected final Log createLog() {
		// normal assert...
		assert(cst!=null):"Constructor null";
		
		try {
			// init our log...
			Log l = (Log) cst.newInstance();
			l.setProperties(p);
			l.init(p);
			return l;
			
		} catch (RuntimeException e) {
			return null;
		} catch (Exception e) {
			return null;
		}
		
	}
	
	
	/**
	 * Create a log with a specific name or return if exists
	 * @param name the name of the log
	 * @return a valid log
	 */
	Log getLog(String name) {
		// normal assert...
		assert(cst != null):"Constructor null";
		
		// find and return if found...
		// otherwise create it...
		Log l = this.findByName(name); // look in the pool...
		if (l!=null) {
			l.setLastUsed(System.currentTimeMillis());
			return l;
		}
		
		// create store and return...
		l =  this.createLog();
		l.setName(name);
		l.setLastUsed(System.currentTimeMillis());
		pool.add(l);
		
		return l;
	}
	
	/**
	 * Get the size of the pool
	 * @return the pool size
	 */
	public int size() {
		if (pool != null)
			return pool.size();
		else 
			return -1;
	}

	/**
	 * Shutdown this LogPool
	 */
	void shutdown() {
		// clean and empty this pool
		if (pool!=null) {
			pool.clear();
			pool=null;
		}
	}	

}
